/* 工具模块 */

/**
 * 消息弹窗及跳转
 * 
 * @param {string}        title    消息文本
 * @param {string}        icon     主题类型 [none / success / loading]
 * @param {Nubmer}        duration 持续时间 [毫秒]
 * @param {string|Nubmer} url      跳转的url (type == 5时，url为返回的页面数)
 * @param {Nubmer}        type     跳转的方式 [1保留跳转 / 2关闭跳转 / 3全关跳转 / 4跳转tab / 5后退返回]
 * @param {Boolean}       mask     是否显示透明蒙层，防止触摸穿透，默认：true
 */
function show(title = '', icon = 'none', duration = 1000, url = null, type = null, mask = true) {
    uni.showToast({ title, icon, duration, mask });
    if (!type) { return; }
    setTimeout(function() { jump(url, type); }, duration);
}

/**
 * 页面跳转
 * 
 * @param {string|Nubmer} url   跳转的url (type == 5时，url为返回的页面数)
 * @param {Nubmer}        type  跳转的方式 [1保留跳转 / 2关闭跳转 / 3全关跳转 / 4跳转tab / 5后退返回]
 */
function jump(url = null, type = 1) {
    switch (type) {
        case 1: // 保留当前页面，跳转到应用内的某个页面
            uni.navigateTo({ url });
            break;
        case 2: // 关闭当前页面，跳转到应用内的某个页面
            uni.redirectTo({ url });
            break;
        case 3: // 关闭所有页面，打开到应用内的某个页面
            uni.reLaunch({ url });
            break;
        case 4: // 跳转到 tabBar 页面，并关闭其他所有非 tabBar 页面
            uni.switchTab({ url });
            break;
        case 5: // 关闭当前页面，返回上一页面或多级页面
            uni.navigateBack({ url });
            break;
    }
}

/**
 * 广告跳转
 * @param {string} url  跳转的url
 * @param {Number} type 跳转的方式
 */
function adJump(url = null, type = 1) {
    switch (type) {
        case 1: // 打开应用内WebView访问H5
            uni.navigateTo({
                url: '/pages/view/view?url=' + encodeURIComponent(url)
            });
            break;
        case 2: // 打开应用内WebView访问文章UID
            uni.navigateTo({
                url: '/pages/view/view?url=' + encodeURIComponent('https://www.xiebutou.com/help/issue/index.html?article_uid=' + url + '&type=h5')
            });
            break;
        case 3: // 跳转应用内指定页面
            uni.navigateTo({
                url: url
            });
            break;
        case 4: // 打开应用外浏览器访问H5
            // #ifdef H5
            // location.href = url;
            window.open(url);
            // #endif
            // #ifdef APP-NVUE
            plus.runtime.openURL(url);
            // #endif
            break;
        case 5: // 弹窗提醒
            this.show(url);
            break;
        default:
            // 不跳转
            break;
    }
}

/**
 * 获取浏览器平台（判断微信或支付宝浏览器）
 */
function getBrowserPlatform() {
    let userAgent = navigator.userAgent.toLowerCase()
    if (userAgent.match(/Alipay/i) == "alipay") {
        return 'alipay';
    } else if (userAgent.match(/MicroMessenger/i) == "micromessenger") {
        return 'wechat';
    } else {
        return '';
    }
}

/**  
 * 获取随机整数
 * 
 * @param {int} min 开始数字
 * @param {int} max 结束数字
 * @param {int} num 生成几组
 * @return {array}
 */
function getRandom(min, max, num = 1) {
    if (num <= 1) {
        return [Math.floor(Math.random() * (max - min + 1)) + min];
    } else {
        let data = [];
        for (let i = 0; i < num; i++) {
            data.push(Math.floor(Math.random() * (max - min + 1)) + min);
        }
        return data;
    }
}

/**
 * 获取订单编号
 */
function getOutTradeNo() {
    return getTime('YmdHis') + getRandom(100000, 999999)[0];
}

/**
 * 获取时间格式
 * 
 * @param {String} format    时间格式[Y-m-d H:i:s]，Y四位年份|y二位年份|H二十四小时制|h十二小时制
 * @param {String} time      秒级时间戳
 * @param {String} microtime 毫秒时间戳
 */
function getTime(format, time = null, microtime = null) {
    let date;
    if (time) {
        date = new Date(time * 1000);
    } else if (microtime) {
        date = new Date(microtime);
    } else {
        date = new Date();
    }
    let opt = {
        'Y': date.getFullYear().toString(),
        'y': date.getFullYear().toString().slice(-2),
        'm': fixZero(date.getMonth() + 1, 2),
        'd': fixZero(date.getDate(), 2),
        'H': fixZero(date.getHours(), 2),
        'h': date.getHours() > 12 ? fixZero(date.getHours() - 12, 2) : fixZero(date.getHours(), 2),
        'i': fixZero(date.getMinutes(), 2),
        's': fixZero(date.getSeconds(), 2),
    };
    for (let key in opt) {
        format = format.replace(key, opt[key]);
    }
    return format;
}

/**
 * 数据补0
 * 
 * @param {String} number 数字
 * @param {Number} length 位数
 * @param {Number} type   类型[1整数前补0 / 2小数后补0]
 */
function fixZero(number, length, type = 1) {
    typeof number != 'string' && (number = number.toString());
    let data = type == 2 ? number.split('.')[1] : number.split('.')[0];
    let zero = '';
    let spot = '';
    if (!data) {
        data = '';
        if (type == 2) spot = '.';
    }
    for (let i = data.length; i < length; i++) {
        zero += '0';
    }
    return type == 2 ? number + spot + zero : zero + number;
}

/**
 * 查询DOM节点数据
 * 
 * @param {Object} e  Vue对象
 * @param {String} name Dom名称，示例值：#name或.name
 * @param {Number} type 类型[1（布局位置） | 2（滚动位置）]
 * @param {Number} mode 方式[1（查询单个） | 2（查询同名多个）]
 */
async function query(e, name, type = 1, mode = 1) {
    return new Promise((resolve, reject) => {
        e.$nextTick(() => {
            let query = uni.createSelectorQuery().in(e);
            query = mode == 1 ? query.select(name) : query.selectAll(name)
            if (type == 1) {
                query.boundingClientRect(data => { resolve(data); }).exec();
            } else {
                query.scrollOffset(data => { resolve(data); }).exec();
            }
        });
    })
}

/**
 * 获取UUID
 */
function getUUID() {
    let uuid = uni.getStorageSync('system_uuid');
    if (uuid) {
        return uuid;
    }
    uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        let r = (Math.random() * 16) | 0;
        let v = c == 'x' ? r : (r & 0x3) | 0x8;
        return v.toString(16);
    });
    uni.setStorageSync('system_uuid', uuid);
    return uuid;
}

/**
 * 判断数据类型
 * 
 * @param {Object} data 数据
 * @param {Number} type [1:对象（包含对象、数组） / 2:对象 / 3:数组 / 4:数字（包含整数、小数） / 5:整数 / 6:小数 / 7:字符串 / 8:布尔值]
 * 
 * @return {Boolean}
 */
function isType(data, type = 1) {
    switch (type) {
        case 1:
            return typeof data === 'object';
        case 2:
            return Object.prototype.toString.call(data) === '[object Object]';
        case 3:
            return Object.prototype.toString.call(data) === '[object Array]';
        case 4:
            return typeof data === 'number';
        case 5:
            return parseInt(data) === parseFloat(data);
        case 6:
            return parseInt(data) !== parseFloat(data);
        case 7:
            return typeof data === 'string';
        case 8:
            return typeof data === 'boolean';
        default:
            return false;
    }
}

/**
 * 获取时间范围
 * 
 * @param {Number} type 时间类型[1今天/2昨天/3本周/4上周/5最近一周/6本月/7上月/8最近一月/9最近三月]
 */
function getDateRange(type) {
    let date = new Date();
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let week = '1234567';
    let day = date.getDate();
    let day1 = date.getDay();
    let first, last;
    switch (type) {
        case 1: // 今天
            first = getIntervalDayDate(0);
            last = getIntervalDayDate(0);
            break;
        case 2: // 昨天
            first = getIntervalDayDate(-1);
            last = getIntervalDayDate(-1);
            break;
        case 3: // 本周
            first = getIntervalDayDate((0 - week.indexOf(day1)));
            last = getIntervalDayDate((6 - week.indexOf(day1)));
            break;
        case 4: // 上周
            first = getIntervalDayDate((0 - week.indexOf(day) - 7));
            last = getIntervalDayDate((6 - week.indexOf(day) - 7));
            break;
        case 5: // 最近一周
            first = getIntervalDayDate((-6));
            last = getIntervalDayDate(0);
            break;
        case 6: // 本月
            day = new Date(year, month, 0);
            first = { year: year, month: month, day: 1 };
            last = { year: year, month: month, day: day.getDate() };
            break;
        case 7: // 上月
            day = new Date(year, month - 1, 0);
            first = { year: year, month: month - 1, day: 1 };
            last = { year: year, month: month - 1, day: day.getDate() };
            break;
        case 8: // 最近一月
            first = getIntervalMonthDate(year, month, day, 1);
            // 开始加一天
            date = new Date(first.year + '-' + fillZero(first.month) + '-' + fillZero(first.day));
            date.setTime(date.getTime() + 24 * 60 * 60 * 1000);
            first = { year: date.getFullYear(), month: fillZero(date.getMonth() + 1), day: fillZero(date.getDate()) };

            last = { year: year, month: month, day: day };
            break;
        case 9: // 最近三月
            first = getIntervalMonthDate(year, month, day, 3);
            // 开始加一天
            date = new Date(first.year + '-' + fillZero(first.month) + '-' + fillZero(first.day));
            date.setTime(date.getTime() + 24 * 60 * 60 * 1000);
            first = { year: date.getFullYear(), month: fillZero(date.getMonth() + 1), day: fillZero(date.getDate()) };

            last = { year: year, month: month, day: day };
            break;
        case 10: // 最近六月
            first = getIntervalMonthDate(year, month, day, 6);
            // 开始加一天
            date = new Date(first.year + '-' + fillZero(first.month) + '-' + fillZero(first.day));
            date.setTime(date.getTime() + 24 * 60 * 60 * 1000);
            first = { year: date.getFullYear(), month: fillZero(date.getMonth() + 1), day: fillZero(date.getDate()) };

            last = { year: year, month: month, day: day };
            break;
        case 11: // 最近一年
            first = getIntervalMonthDate(year, month, day, 12);
            // 开始加一天
            date = new Date(first.year + '-' + fillZero(first.month) + '-' + fillZero(first.day));
            date.setTime(date.getTime() + 24 * 60 * 60 * 1000);
            first = { year: date.getFullYear(), month: fillZero(date.getMonth() + 1), day: fillZero(date.getDate()) };

            last = { year: year, month: month, day: day };
            break;
        default:
            return '';
    }
    return first.year + '-' + fillZero(first.month) + '-' + fillZero(first.day) + ' ~ ' + last.year + '-' + fillZero(last.month) + '-' + fillZero(last.day);
}

/**
 * 获取间隔天数后的日期
 * 
 * @param {Number} interval 间隔天数（可以是负数）
 */
function getIntervalDayDate(interval) {
    let date = new Date();
    date.setDate(date.getDate() + interval);
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let day = date.getDate();
    return { year: year, month: month, day: day };
}

/**
 * 获取间隔月数后的日期
 * 
 * @param {Number|String} year     年
 * @param {Number|String} month    月
 * @param {Number|String} day      日
 * @param {Number}        interval 间隔月数
 */
function getIntervalMonthDate(year, month, day, interval) {
    let end = new Date(year, month, 0).getDate();
    if (month - interval <= 0) {
        let start = new Date((year - 1), (12 - (interval - parseInt(month))), 0).getDate();
        if (start < day) {
            return { year: (year - 1), month: (12 - (interval - month)), day: start };
        } else {
            return { year: (year - 1), month: (12 - (interval - month)), day: day };
        }
    } else {
        let start = new Date(year, (parseInt(month) - interval), 0).getDate();
        if (start < day) {
            return { year: year, month: (month - interval), day: start };
        } else {
            return { year: year, month: (month - interval), day: day };
        }
    }
}

/**
 * 月日补0
 * 
 * @param {Number|String} date 月或日
 */
function fillZero(date) {
    date = parseInt(date);
    return date < 10 ? '0' + date : date;
}

/**
 * 对象或字符串转数组
 * 
 * @param {Object|String} data
 */
function toArray(data) {
    let array = [];
    for (let i in data) {
        array.push(data[i]);
    }
    return array;
}

/**
 * 倒计时
 */
function countDown(createDate, limitTimes) {
    limitTimes = limitTimes * 60
    let now = new Date();
    let create = new Date(createDate);
    let nowSecond = now.getTime();
    let createSecond = create.getTime();
    let countSecond = parseInt((nowSecond - createSecond) / 1000);
    let times = limitTimes - countSecond
    return {
        day: parseInt(times / 86400),
        hour: parseInt(times / 3600),
        minute: parseInt(times / 60),
        second: parseInt(times % 60)
    }
}

/**
 * 切换开发环境
 */
function changeDevelopMode() {
    if (this.develop_num == 0) {
        uni.removeStorageSync('develop_mode');
        this.develop_mode = 0;
        this.show('已经切换到 生产环境');
    } else if (this.develop_num == 15) {
        uni.setStorageSync('develop_mode', 1);
        this.develop_mode = 1;
        this.show('已经切换到 开发环境');
    } else if (this.develop_num == 30) {
        this.develop_num = 0;
        return;
    }
    this.develop_num++;
}

module.exports = {
    show,
    jump,
    adJump,
    getBrowserPlatform,
    getRandom,
    getOutTradeNo,
    getTime,
    fixZero,
    query,
    getUUID,
    isType,
    toArray,
    changeDevelopMode,
    getDateRange,
    countDown
}
